package gogo

import (
	"net/http"
	"strings"
	"sync"
)

// 固定URL前缀的钩子结构体
type preMuxEntry struct {
	h       preHttpProcFunc
	pattern string
}

// 固定URL结构体
type staticMuxEntry struct {
	h       HttpProcFunc
	pattern string
}

// 含有":"的智能URL结构体
type imuxEntry struct {
	h         HttpProcFunc
	pattern   string
	urlParams []string
}

// httpRouterHandler 保存注册函数的地方
type httpRouterHandler struct {
	mu sync.RWMutex

	//静态路径匹配
	pm map[string]string

	//特殊STATE匹配
	sm map[int]staticMuxEntry

	//固定URL前缀特征匹配，钩子规则
	//map["GET"/"POST"][pattern]staticMuxEntry
	pre_gm map[string]map[string]preMuxEntry

	//固定特征的URL匹配
	//map["GET"/"POST"][pattern]staticMuxEntry
	gm map[string]map[string]staticMuxEntry

	//含有":"的智能URL匹配
	//map["GET"/"POST"][]imuxEntry
	im map[string][]imuxEntry

	//hosts bool // whether any patterns contain hostnames
}

// ServeHTTP 官方HTTP触发入口
func (mux *httpRouterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	pctx := &HTTPContext{w: w, r: r}

	//固定URL前缀特征匹配，钩子规则
	if v, ok := mux.pre_gm[r.Method]; ok {
		for prefix, proc := range v {
			if strings.HasPrefix(r.URL.Path, prefix) {
				if !proc.h.PreServeHTTP(pctx) {
					return
				}
			}
		}
	}

	//匹配固定URL规则
	if v, ok := mux.gm[r.Method][r.URL.Path]; ok {
		v.h.ServeHTTP(pctx)
		return
	}

	//匹配智能URL规则
	for _, v := range mux.im[r.Method] {

		if strings.HasPrefix(r.URL.Path, v.pattern) {
			urlParams := strings.Split(string([]byte(r.URL.Path)[len(v.pattern)+1:]), "/")

			if len(urlParams) == len(v.urlParams) {
				extURLParams := make(map[string]string)
				foundSuss := true

				for urlParamsID, urlParamsValue := range urlParams {

					if strings.HasPrefix(v.urlParams[urlParamsID], ":") {
						extURLParams[v.urlParams[urlParamsID]] = urlParamsValue

					} else if urlParamsValue != v.urlParams[urlParamsID] {
						foundSuss = false
						break
					}
				}

				if foundSuss {
					pctx.urlParams = extURLParams
					v.h.ServeHTTP(pctx)
					return
				}
			}
		}
	}

	//匹配静态路径规则
	if r.Method == "GET" {
		for pattern, path := range mux.pm {
			if strings.HasPrefix(r.URL.Path, pattern) {
				filePath := path + strings.TrimPrefix(r.URL.Path, pattern)
				http.ServeFile(w, r, filePath)
				return
			}
		}
	}

	if v, ok := mux.sm[http.StatusNotFound]; ok {
		v.h.ServeHTTP(pctx)
	}
}

func (mux *httpRouterHandler) RegHTTPPublic(pattern, path string) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if pattern == "" {
		panic("http: invalid pattern")
	}
	if path == "" {
		panic("http: invalid path")
	}

	if !strings.HasSuffix(pattern, "/") {
		pattern += "/"
	}

	if !strings.HasSuffix(path, "/") {
		path += "/"
	}

	//检查pattern是否之前已经添加过
	if _, exist := mux.pm[pattern]; exist {
		panic("http: multiple registrations for " + pattern)
	}

	if mux.pm == nil {
		mux.pm = make(map[string]string)
	}

	mux.pm[pattern] = path
}

func (mux *httpRouterHandler) RegHTTPPreFunc(method, pattern string, handler preHttpProcFunc) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if pattern == "" {
		panic("http: invalid pattern")
	}
	if handler == nil {
		panic("http: nil handler")
	}

	//检查pattern是否之前已经添加过
	if _, exist := mux.pre_gm[pattern]; exist {
		panic("http: multiple registrations for " + pattern)
	}

	if mux.pre_gm == nil {
		mux.pre_gm = make(map[string]map[string]preMuxEntry)
	}
	if mux.pre_gm[method] == nil {
		mux.pre_gm[method] = make(map[string]preMuxEntry)
	}

	mux.pre_gm[method][pattern] = preMuxEntry{h: handler, pattern: pattern}
}

// RegHTTPProcFunc 注册固定URL、解析URL函数
// method string: 请求方式，POST、GET、PUT、DELETE等
// pattern string：触发路径
// handler httpProcFunc: 触发函数
func (mux *httpRouterHandler) RegHTTPProcFunc(method, pattern string, handler HttpProcFunc) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if pattern == "" {
		panic("http: invalid pattern")
	}
	if handler == nil {
		panic("http: nil handler")
	}

	//检查pattern是否之前已经添加过
	if _, exist := mux.gm[pattern]; exist {
		panic("http: multiple registrations for " + pattern)
	}
	if _, exist := mux.im[pattern]; exist {
		panic("http: multiple registrations for " + pattern)
	}

	if mux.gm == nil {
		mux.gm = make(map[string]map[string]staticMuxEntry)
	}
	if mux.gm[method] == nil {
		mux.gm[method] = make(map[string]staticMuxEntry)
	}

	if mux.im == nil {
		mux.im = make(map[string][]imuxEntry)
	}
	if mux.im[method] == nil {
		mux.im[method] = []imuxEntry{}
	}

	istart := strings.Index(pattern, "/:")
	if istart == -1 {
		mux.gm[method][pattern] = staticMuxEntry{h: handler, pattern: pattern}
	} else {
		if istart <= 1 {
			Log().Error(pattern + "错误,请不要以\\:开头!")
		} else {
			ipattern := string([]byte(pattern)[:istart])
			urlParams := strings.Split(string([]byte(pattern)[istart+1:]), "/")
			mux.im[method] = append(mux.im[method], imuxEntry{h: handler, urlParams: urlParams, pattern: ipattern})
		}
	}

	/*if pattern[0] != '/' {
		mux.hosts = true
	}*/
}

// RegHTTPStatusFunc 注册指定HTTP状态触发的函数
// status int: HTTP状态, 参考net\http\status.go
// handler httpProcFunc: 触发函数
func (mux *httpRouterHandler) RegHTTPStatusFunc(status int, handler HttpProcFunc) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if status == 0 {
		panic("http: invalid status")
	}
	if handler == nil {
		panic("http: nil handler")
	}

	if mux.sm == nil {
		mux.sm = make(map[int]staticMuxEntry)
	}

	mux.sm[status] = staticMuxEntry{h: handler, pattern: "404"}
}
